import { isFunciton } from "@vue/shared";
import { effect, track, trigger } from "./effect";
import { TrackOpTypes, TriggerOrTypes } from "./operators";

class ComputedRefImpl {
  public _dirty = true; // 默认取值不用缓存
  public _value;

  private effect;

  constructor(public getter, public setter) {
    // 计算属性默认生成一个 effect
    this.effect = effect(getter, {
      lazy: true,
      scheduler: () => {
        if (!this._dirty) {
          this._dirty = true;
          // 触发依赖，更新视图
          trigger(this, TriggerOrTypes.SET, 'value');
        }
      }
    });
  }

  get value() {
    if (this._dirty) {
      this._value = this.effect();
      this._dirty = false;
    }
    // 收集依赖
    track(this, TrackOpTypes.GET, 'value');
    return this._value;
  }
  set value(newValue) {
    this.setter(newValue);
  }
}

// vue2 计算属性不需要收集依赖,vue3 需要收集依赖

export function computed(getterOrOptions) {
  let getter;
  let setter;

  if (isFunciton(getterOrOptions)) {
    getter = getterOrOptions;
    setter= () => {
      console.warn('computed value must be readonly');
    }
  } else {
    getter = getterOrOptions.get;
    setter = getterOrOptions.set;
  }

  return new ComputedRefImpl(getter, setter);
}